package com.bajiao.service.user.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.bajiao.common.constant._Whole;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.util.DateUtils;
import com.bajiao.common.util.FastJsonHelper;
import com.bajiao.common.util.RedisUtil;
import com.bajiao.common.util.UUIDGenerator;
import com.bajiao.entity.coupon.Coupon;
import com.bajiao.entity.order.CouponOrder;
import com.bajiao.entity.user.UserCoupon;
import com.bajiao.mapper.user.UserCouponMapper;
import com.bajiao.service.order.CouponOrderService;
import com.bajiao.service.store.StoreService;
import com.bajiao.service.user.UserCouponService;
import com.bajiao.vo.coupon.CouponResponse;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 用户优惠券表
 * @Author: FanJq
 * @Date:   2024-12-13
 * @Version: V1.0
 */
@Service
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements UserCouponService {

    @Lazy
    @Resource
    private CouponOrderService couponOrderService;
    @Resource
    private RedisUtil redisUtil;

    /**
     * @Description
     * 获取用户拥有的指定优惠券数量
     * @date 2024/12/13 16:56
     * @author FanJq
     * @param userId
     * @param couponId
     * @return {@link Integer}
    */
    @Override
    public Integer getUserHasCount(String userId, String couponId) {
        Integer count = super.lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(StrUtil.isNotBlank(couponId), UserCoupon::getCouponId, couponId)
                .eq(UserCoupon::getStatus, _Whole.ONE)
                .count();
        return count;
    }

    /**
     * @Description
     * 获取用户优惠券
     * @date 2024/12/18 15:08
     * @author FanJq
     * @param userId
     * @param couponId
     * @return {@link UserCoupon}
    */
    @Override
    public UserCoupon getUserUsableCoupon(String userId, String couponId) {
        UserCoupon userCoupon = super.lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getCouponId, couponId)
                .eq(UserCoupon::getStatus, _Whole.ONE)
                .orderByAsc(UserCoupon::getExpireTime)
                .last("LIMIT 1")
                .one();
        return userCoupon;
    }

    /**
     * @Description
     * 获取用户拥有的优惠券
     * @date 2024/12/13 17:30
     * @author FanJq
     * @param userId
     * @param storeId
     * @return {@link List< CouponResponse>}
    */
    @Override
    public List<CouponResponse> getUserHasCoupon(String userId, String storeId) {
        List<UserCoupon> couponList = super.lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getStatus, _Whole.ONE)
                .and(sql -> sql.eq(UserCoupon::getStoreId, storeId)
                        .or().isNull(UserCoupon::getStoreId))
                .list();
//        Map<String, String> storeTitleMap = new HashMap<>();
        List<CouponResponse> responseList = couponList.stream().map(coupon -> {
            CouponResponse response = FastJsonHelper.beanToBean(coupon, CouponResponse.class);
            response.setQuota(coupon.getQuota().stripTrailingZeros().toPlainString());
//            if (response.getType() == _Whole.ONE) {
//                response.setQuota(coupon.getQuota().multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString());
//            }
            response.setIsHas(_Whole.ONE);
//            if (coupon.getScope().intValue() == _Whole.TWO) {
//                if (!storeTitleMap.containsKey(coupon.getStoreId())) {
//                    String storeTitle = storeService.getStoreTitle(coupon.getStoreId());
//                    storeTitleMap.put(coupon.getStoreId(), storeTitle);
//                }
//                response.setStoreTitle(storeTitleMap.get(coupon.getStoreId()));
//            }
            return response;
        }).collect(Collectors.toList());
        return responseList;
    }

    /**
     * @Description
     * 使用优惠券
     * @date 2024/12/16 10:07
     * @author FanJq
     * @param status
     * @return
    */
    @Override
    @Async("taskExecutor")
    public void useCoupon(UserCoupon userCoupon, Integer status) {
        if (ObjectUtil.isNull(userCoupon) || userCoupon.getStatus().intValue() != _Whole.ONE)
            return;
        if (status.intValue() < _Whole.TWO || status.intValue() > _Whole.THREE)
            throw new DataHandleException("优惠券状态异常");
        userCoupon.setStatus(status);
        //@create by FanJq 2024/12/16 10:31 初始化更新sql
        LambdaUpdateChainWrapper<UserCoupon> updateSql = super.lambdaUpdate()
                .set(UserCoupon::getStatus, userCoupon.getStatus())
                .eq(UserCoupon::getUserId, userCoupon.getUserId())
                .eq(UserCoupon::getId, userCoupon.getId());
        if (userCoupon.getStatus().intValue() == _Whole.THREE) {
            //@create by FanJq 2024/12/16 10:25 核销优惠券
            Date verifyTime = new Date();
            updateSql.set(UserCoupon::getVerifyTime, verifyTime);
            userCoupon.setVerifyTime(verifyTime);
        }
        //@create by FanJq 2024/12/16 10:14 更新优惠券状态
        Boolean b = updateSql.update();
        if (b && StrUtil.isNotBlank(userCoupon.getOrderNo())) {
            //@create by FanJq 2024/12/19 10:50 同步订单状态
            couponOrderService.syncStatus(userCoupon);
            //@create by FanJq 2024/12/19 10:58 清除redis队列中过期事件
            String redisKey = _Whole.couponExpiredKey + userCoupon.getId();
            if (redisUtil.hasKey(redisKey))
                redisUtil.del(redisKey);
        }
    }

    /**
     * @Description
     * 获取用户优惠券
     * @date 2024/12/16 10:10
     * @author FanJq
     * @param userId
     * @param userCouponId
     * @return {@link UserCoupon}
    */
    @Override
    public UserCoupon getById(String userId, String userCouponId) {
        return super.lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getId, userCouponId)
                .one();
    }

    /**
     * @Description
     * 创建用户优惠券
     * @date 2024/12/18 16:42
     * @author FanJq
     * @param userId
     * @param coupon
     * @param orderNo
     * @return {@link UserCoupon}
    */
    @Override
    public UserCoupon create(String userId, Coupon coupon, String orderNo) {
        Date receiveTime = new Date();
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setUserId(userId);
        userCoupon.setCouponId(coupon.getId());
        userCoupon.setTitle(coupon.getTitle());
        userCoupon.setReceiveTime(receiveTime);
        userCoupon.setExpireTime(DateUtils.addDay(receiveTime, coupon.getDays()));
        userCoupon.setScope(coupon.getScope());
        userCoupon.setType(coupon.getType());
        userCoupon.setQuota(coupon.getQuota());
        userCoupon.setStoreId(coupon.getStoreId());
        userCoupon.setOrderNo(orderNo);
        userCoupon.setVerifyCode(getVerifyCode());
        super.save(userCoupon);
        return userCoupon;
    }

    /**
     * @Description
     * 获取今日到期的用户优惠券
     * @date 2024/12/19 10:02
     * @author FanJq
     * @param
     * @return {@link List< UserCoupon>}
    */
    @Override
    public List<UserCoupon> getTodayExpire() {
        //@create by FanJq 2024/12/20 15:00 处理异常订单
        String today = DateUtils.date_sdf.get().format(new Date());
        List<UserCoupon> resultList = super.lambdaQuery()
                .eq(UserCoupon::getStatus, _Whole.ONE)
                .apply("date_format(expire_time, '%Y-%m-%d') = {0}", today)
                .list();
        return resultList;
    }

    /**
     * @Description
     * 获取已过期的
     * @date 2024/12/20 15:03
     * @author FanJq
     * @param
     * @return {@link List< UserCoupon>}
    */
    @Override
    public List<UserCoupon> getExpired() {
        List<UserCoupon> resultList = super.lambdaQuery()
                .eq(UserCoupon::getStatus, _Whole.ONE)
                .apply("expire_time < CURRENT_TIMESTAMP")
                .list();
        return resultList;
    }

    /**
     * @Description
     * 执行优惠券到期事件
     * @date 2024/12/19 10:31
     * @author FanJq
     * @param userCoupon
     * @return
    */
    @Override
    @Async("taskExecutor")
    @Transactional(rollbackFor = Exception.class)
    public void expiredEvent(UserCoupon userCoupon) {
        userCoupon.setStatus(_Whole.ZERO);
        Boolean b = super.lambdaUpdate()
                .set(UserCoupon::getStatus, userCoupon.getStatus())
                .eq(UserCoupon::getId, userCoupon.getId())
                .update();
        if (b && StrUtil.isNotBlank(userCoupon.getOrderNo())) {
            //@create by FanJq 2024/12/19 10:37 同步订单状态
            couponOrderService.syncStatus(userCoupon);
        }
    }

    /**
     * @Description
     * 根据订单编号获取
     * @date 2024/12/20 15:18
     * @author FanJq
     * @param userId
     * @param orderNo
     * @return {@link UserCoupon}
    */
    @Override
    public UserCoupon getByOrderNo(String userId, String orderNo) {
        return super.lambdaQuery()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getOrderNo, orderNo)
                .one();
    }

    /**
     * @Description
     * 根据用户id获取
     * @date 2024/12/24 17:07
     * @author FanJq
     * @param userId
     * @return {@link List< CouponResponse>}
    */
    @Override
    public List<CouponResponse> getByUserId(String userId) {
        List<UserCoupon> userCouponList = super.baseMapper.getUserCouponList(userId);
        List<CouponResponse> responseList = userCouponList.stream().map(model -> {
            CouponResponse response = FastJsonHelper.beanToBean(model, CouponResponse.class);
            response.setQuota(model.getQuota().stripTrailingZeros().toPlainString());
//            if (response.getType() == _Whole.ONE) {
//                response.setQuota(model.getQuota().multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString());
//            }
            response.setIsHas(_Whole.ONE);
            return response;
        }).collect(Collectors.toList());
        return responseList;
    }

    /**
     * @Description
     * 根据核销码获取
     * @date 2024/12/26 14:32
     * @author FanJq
     * @param verifyCode
     * @return {@link UserCoupon}
    */
    @Override
    public UserCoupon getByVerifyCode(String verifyCode) {
        UserCoupon userCoupon = super.lambdaQuery()
                .eq(UserCoupon::getVerifyCode, verifyCode)
                .one();
        return userCoupon;
    }

    /**
     * @Description
     * 获取核销码
     * @date 2024/12/18 16:14
     * @author FanJq
     * @param
     * @return {@link String}
     */
    public String getVerifyCode() {
        String verifyCode = UUIDGenerator.getRandom620(13);
        Integer count = super.lambdaQuery()
                .select(UserCoupon::getId)
                .eq(UserCoupon::getVerifyCode, verifyCode)
                .count();
        if (count > _Whole.ZERO)
            this.getVerifyCode();
        return verifyCode;
    }
}
